/*
 * Copyright (c) 2024 Shenzhen Kaihong Digital Industry Development Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "station_controller.h"

#include <cstddef>
#include <string>
#include <unordered_map>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <sys/random.h>

#include "iot_connect_log.h"
#include "sle_bridge_errors.h"
#include "sle_thing_model_define.h"
#include "parameter.h"
namespace OHOS {
namespace iotConnect {
SleBaseDeviceInfo StationController::sleBaseDeviceInfo_ = {"skh", "000001", "123", PERR_CONNECT_TYPE_OFFLINE};
SleBaseWiFiInfo StationController::sleBaseWiFiInfo_ = {};
SleBaseSleInfo StationController::sleBaseSleInfo_ = {};
ConfigurationManagementInfo StationController::configurationManagementInfo_ = {};
SleBaseCPUInfo StationController::sleBaseCPUInfo_ = {};
SleBaseOSInfo StationController::sleBaseOSInfo_ = {};
SleBaseOTAInfo StationController::sleBaseOTAInfo_ = {};
SleBaseRestartInfo StationController::sleBaseRestartInfo_ = {};
SleBaseFactoryReset StationController::sleBaseFactoryReset_ = {};
constexpr int RANDOM_NUMBER_RANGE = 1000000;
constexpr int BASE_YEAR = 1900;
constexpr int MONTH_OFFSET = 1;
#define JSON_STR_SNW "snw"

cJSON *StationController::IotcCharStateToJson(const IotcCharState *state) const
{
    if (state == NULL) {
        return NULL;
    }
    HILOGE("IotcCharStateToJson in");
    cJSON *root = cJSON_CreateObject();
    if (root == NULL) {
        return NULL;
    }

    // 添加各个字段
    cJSON_AddStringToObject(root, "svcId", state->svcId ? state->svcId : "");
    HILOGE("IotcCharStateToJson svcId");
    cJSON *parsedData = cJSON_Parse(state->data); // 解析成 cJSON 对象
    if (parsedData) {
        cJSON_AddItemToObject(root, "data", parsedData); // 作为 JSON 对象添加
    } else {
        // 解析失败则按原始字符串添加
        cJSON_AddStringToObject(root, "data", state->data ? state->data : "");
    }

    HILOGE("IotcCharStateToJson data");
    cJSON_AddNumberToObject(root, "len", state->len);
    HILOGE("IotcCharStateToJson len");
#if IOTC_CONF_DEV_TYPE == 2
    cJSON_AddStringToObject(root, "devId", state->devId ? state->devId : "");
    HILOGE("IotcCharStateToJson devId");
    cJSON_AddStringToObject(root, "msgId", state->msgId ? state->msgId : "");
    HILOGE("IotcCharStateToJson msgId");
#endif
    return root; // 返回 cJSON 对象，由调用者决定打印/释放
    free(parsedData);
}

std::string StationController::GenerateUniqueMsgSeq() const
{
    struct timespec ts;
    clock_gettime(CLOCK_REALTIME, &ts);
    long ms = ts.tv_nsec / RANDOM_NUMBER_RANGE;

    char buffer[64] = {0};
    std::tm tmTime;
    localtime_r(&ts.tv_sec, &tmTime);

    unsigned int secureRandom = 0;
    getrandom(&secureRandom, sizeof(secureRandom), 0);
    secureRandom %= RANDOM_NUMBER_RANGE;
    int result = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "%04d%02d%02d%02d%02d%02d%03ld-%06u",
        tmTime.tm_year + BASE_YEAR, tmTime.tm_mon + MONTH_OFFSET, tmTime.tm_mday, tmTime.tm_hour, tmTime.tm_min,
        tmTime.tm_sec, ms, secureRandom);
    if (result < 0 || result >= static_cast<int>(sizeof(buffer))) {
        HILOGE("snprintf_s failed or buffer overflow, result: %d", result);
        // 使用时间戳作为备选方案，确保总是有有效的消息序列号
        return std::string("FALLBACK_") + std::to_string(ts.tv_sec);
    }
    return std::string(buffer);
}

int32_t StationController::DevInfoGetCharState(const IotcCharState inData, std::string *data, uint32_t *len) const
{
    cJSON *json = IotcCharStateToJson(&inData);
    if (nullptr == json) {
        HILOGE("create json error");
        return -1;
    }
    std::string uniqueKey = GenerateUniqueMsgSeq();
    if (cJSON_AddStringToObject(json, "msgSeq", uniqueKey.c_str()) == nullptr) {
        cJSON_Delete(json);
        HILOGE("add uniqueKey error");
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }

    if (cJSON_AddStringToObject(json, "brand", GetBrand()) == nullptr) {
        cJSON_Delete(json);
        HILOGE("add brand error");
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }

    if (cJSON_AddStringToObject(json, "serialNumber", GetSerial()) == nullptr) {
        cJSON_Delete(json);
        HILOGE("add serialNumber error");
        return SLE_BRIDGE_ERR_ADD_JSON_DATA;
    }

    *data = cJSON_PrintUnformatted(json);
    *len = data->length();
    return SLE_BRIDGE_SUCCESS;
}

int32_t StationController::ConfigurationManagementGetCharState(
    const IotcCharState inData, std::string *data, uint32_t *len)
{
    return SLE_BRIDGE_SUCCESS;
}

int32_t StationController::ConfigurationManagementPutCharState(
    const IotcCharState inData, const char *data, uint32_t len)
{
    return SLE_BRIDGE_SUCCESS;
}

extern IotcDeviceInfo DEV_INFO;

int32_t StationController::GetSn(std::string *data, uint32_t *len)
{
    if (data == NULL) {
        IOTC_LOGE("param invalid");
        return -1;
    }

    cJSON *json = cJSON_CreateObject();
    if (json == NULL) {
        IOTC_LOGE("create obj error");
        return -1;
    }

    if (cJSON_AddStringToObject(json, JSON_STR_SNW, DEV_INFO.sn) == NULL) {
        cJSON_Delete(json);
        IOTC_LOGE("add num error");
        return -1;
    }
    std::string tempData = cJSON_PrintUnformatted(json);
    if (!tempData.empty()) {
        *data = tempData;
        *len = tempData.length();
        IOTC_LOGI("sn on get %s", DEV_INFO.sn);
    }
    cJSON_Delete(json);

    return SLE_BRIDGE_SUCCESS;
}

int32_t StationController::InternalHandler(const IotcCharState inData, std::string &out, ThingModelPutOrGet flag)
{
    auto iter = mapThingModelSvcStation.find(std::string(inData.svcId));
    if (mapThingModelSvcStation.end() == iter) {
        HILOGE("not find svrId, svrId:%{public}s", inData.svcId);
        return SLE_BRIDGE_ERR_INVALID_PARAM;
    }

    SvcType type = static_cast<SvcType>(iter->second);
    switch (type) {
        case SvcType::DEV_INFO: {
            if (flag == ThingModelPutOrGet::GET) {
                std::string tempOut;
                uint32_t tempLen = 0;
                this->DevInfoGetCharState(inData, &tempOut, &tempLen);
                if (!tempOut.empty()) {
                    out = tempOut;
                }
            }
            break;
        }
        case SvcType::CONFIGURATION_MAG: {
            if (ThingModelPutOrGet::GET == flag) {
                std::string tempOut;
                uint32_t tempLen = 0;
                this->ConfigurationManagementGetCharState(inData, &tempOut, &tempLen);
                if (!tempOut.empty()) {
                    out = tempOut;
                }
            } else {
                this->ConfigurationManagementPutCharState(inData, nullptr, 0);
            }
            break;
        }
        case SvcType::GET_SN: {
            if (ThingModelPutOrGet::GET == flag) {
                std::string tempOut;
                uint32_t tempLen = 0;
                this->GetSn(&tempOut, &tempLen);
                if (!tempOut.empty()) {
                    out = tempOut;
                }
            }
            break;
        }
        default: {
            HILOGE("svrId not in mapThingModelSvcStation, svrId:%{public}s", inData.svcId);
            break;
        }
    }
    return SLE_BRIDGE_SUCCESS;
}

int32_t StationController::GetSleBaseDeviceInfo(SleBaseDeviceInfo &devInfo)
{
    devInfo = sleBaseDeviceInfo_;
    return SLE_BRIDGE_SUCCESS;
}
int32_t StationController::GetAllInfoHandler(const std::string &devId, IotcCharState *state)
{
    return SLE_BRIDGE_SUCCESS;
}
} // namespace iotConnect
} // namespace OHOS
